using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using RPG.Infrastructure.Core;
using UnityEngine;

namespace RPG.Infrastructure.Events
{
    public class UnityEventBus : IEventBus
    {
        private readonly Dictionary<Type, List<object>> _handlers = new();

        public async Task PublishAsync<TEvent>(TEvent @event) where TEvent : DomainEvent
        {
            var eventType = typeof(TEvent);
            if (!_handlers.ContainsKey(eventType))
                return;

            foreach (var handler in _handlers[eventType])
            {
                try
                {
                    await ((IEventHandler<TEvent>)handler).HandleAsync(@event);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Error handling event {eventType.Name}: {ex}");
                }
            }
        }

        public void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : DomainEvent
        {
            var eventType = typeof(TEvent);
            if (!_handlers.ContainsKey(eventType))
                _handlers[eventType] = new List<object>();

            _handlers[eventType].Add(handler);
        }

        public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : DomainEvent
        {
            var eventType = typeof(TEvent);
            if (!_handlers.ContainsKey(eventType))
                return;

            _handlers[eventType].Remove(handler);
            
            if (_handlers[eventType].Count == 0)
                _handlers.Remove(eventType);
        }
    }
}
